class ReactiveManger {
    changes = new Map()
    isBatch = false
    onChanged = (_target, _prop, _value) => {}

    constructor(onChanged) {
        this.onChanged = onChanged
    }

    ref(target) {
        const handler = {
            set: (target, prop, value) => {
                if (this.isBatch) {
                    let change = this.changes.get(target)
                    if (change) {
                        change[prop] = value
                    } else {
                        change = {}
                        change[prop] = value
                        this.changes.set(target, change)
                    }
                } else {
                    this.trigger(target, prop, value)
                }
                return Reflect.set(target, prop, value)
            }
        }
        return new Proxy(target, handler)
    }

    begingBatch() {
        this.isBatch = true
        this.changes.clear()
    }

    commit() {
        this.isBatch = false
        for (const [target, change] of this.changes) {
            this.trigger(target, change)
            this.changes.delete(target)
        }
    }

    trigger(target, prop, value) {
        this.onChanged?.(target, prop, value)
    }

    clear() {
        this.changes.clear()
    }
}

module.exports = ReactiveManger
